﻿using System;
using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Xml;

using Microsoft.Samples.Office.UnifiedCommunications.Gadget.Config;

namespace Microsoft.Samples.Office.UnifiedCommunications.Gadget.EWSUtility
{
    public class EWSVoicemail
    {
        #region Sample Soap Responses

        #region Get Voicemail Folder - Success
        /*
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Header>
    <t:ServerVersionInfo MajorVersion="8" MinorVersion="1" MajorBuildNumber="263" MinorBuildNumber="0" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" />
  </soap:Header>
  <soap:Body>
    <m:GetFolderResponse xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
      <m:ResponseMessages>
        <m:GetFolderResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:Folders>
            <t:SearchFolder>
              <t:FolderId Id="AQAbAGdlb3JnZS5kdXJ6aUBjbGFyaXR5Y29uLmNvbQAuAAADyUsfVZmGXEKAFDMI1GzneQEAysYmSnJevESCh11jID8gRwABmYTfyAAAAA==" ChangeKey="CAAAABYAAADKxiZKcl68RIKHXWMgPyBHAAGZh0rN" />
              <t:ParentFolderId Id="AQAbAGdlb3JnZS5kdXJ6aUBjbGFyaXR5Y29uLmNvbQAuAAADyUsfVZmGXEKAFDMI1GzneQEAysYmSJevESCh11jID8gRwABZRpaAwAAAA==" ChangeKey="AQAAAA==" />
              <t:FolderClass>IPF.Note.Microsoft.Voicemail</t:FolderClass>
              <t:DisplayName>Voice Mail</t:DisplayName>
              <t:TotalCount>0</t:TotalCount>
              <t:ChildFolderCount>0</t:ChildFolderCount>
              <t:UnreadCount>0</t:UnreadCount>
            </t:SearchFolder>
          </m:Folders>
        </m:GetFolderResponseMessage>
      </m:ResponseMessages>
    </m:GetFolderResponse>
  </soap:Body>
</soap:Envelope>
        */ 
        #endregion

        #region Get Voicemails
        /*
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Header>
    <t:ServerVersionInfo MajorVersion="8" MinorVersion="1" MajorBuildNumber="263" MinorBuildNumber="0" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" />
  </soap:Header>
  <soap:Body>
    <m:FindItemResponse xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
      <m:ResponseMessages>
        <m:FindItemResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:RootFolder TotalItemsInView="2" IncludesLastItemInRange="true">
            <t:Items>
              <t:Message>
                <t:ItemId Id="AAAbAGdlb3JnZS5kdXJ6aUBjbGFyaXR5Y29uLmNvbQBGAAAAAADJSx9VmYZcQoAUMwjUbOd5BwDKxiZKcl68RIKHXWMgPyBHAAFlGln/AADKxiZKcl68RIKHXWMgPyBHAAGZgAd4AAA=" ChangeKey="CQAAABYAAADKxiZKcl68RIKHXWMgPyBHAAGZnK5a" />
                <t:Subject>Voice Mail from Test Consultant (3 seconds)</t:Subject>
                <t:Sensitivity>Normal</t:Sensitivity>
                <t:Size>16466</t:Size>
                <t:DateTimeSent>2008-03-24T20:07:26Z</t:DateTimeSent>
                <t:DateTimeCreated>2008-03-24T20:07:27Z</t:DateTimeCreated>
                <t:HasAttachments>true</t:HasAttachments>
                <t:From>
                  <t:Mailbox>
                    <t:Name>Test Consultant</t:Name>
                  </t:Mailbox>
                </t:From>
                <t:IsRead>false</t:IsRead>
              </t:Message>
              <t:Message>
                <t:ItemId Id="AAAbAGdlb3JnZS5kdXJ6aUBjbGFyaXR5Y29uLmNvbQBGAAAAAADJSx9VmYZcQoAUMwjUbOd5BwDKxiZKcl68RIKHXWMgPyBHAAFlGln/AADKxiZKcl68RIKHXWMgPyBHAAGZgAd3AAA=" ChangeKey="CQAAABYAAADKxiZKcl68RIKHXWMgPyBHAAGZnK5A" />
                <t:Subject>Voice Mail from Test Consultant (3 seconds)</t:Subject>
                <t:Sensitivity>Normal</t:Sensitivity>
                <t:Size>17137</t:Size>
                <t:DateTimeSent>2008-03-24T20:06:57Z</t:DateTimeSent>
                <t:DateTimeCreated>2008-03-24T20:06:57Z</t:DateTimeCreated>
                <t:HasAttachments>true</t:HasAttachments>
                <t:From>
                  <t:Mailbox>
                    <t:Name>Test Consultant</t:Name>
                  </t:Mailbox>
                </t:From>
                <t:IsRead>true</t:IsRead>
              </t:Message>
            </t:Items>
          </m:RootFolder>
        </m:FindItemResponseMessage>
      </m:ResponseMessages>
    </m:FindItemResponse>
  </soap:Body>
</soap:Envelope>
        */
        #endregion

        #endregion

        public delegate bool IsEnabledDelegate(EWSRequest ewsRequest);
        public delegate int GetNumberUnreadVoicemailsDelegate(EWSRequest ewsRequest);
        public delegate List<VoicemailMessage> GetVoicemailsDelegate(EWSRequest ewsRequest);

        public static bool IsEnabled(EWSRequest ewsRequest)
        {       
            bool isEnabled;

            try
            {
                XmlDocument vmXmlDoc = ewsRequest.GetFolderByDistinguishedFolderId(EWSEnums.DistinguishedFolderId.voicemail);
                XmlNamespaceManager xmlNamespaceManager = EWSRequest.CreateRequestXmlNamespaceManager(vmXmlDoc);

                // Xml looks like --> <m:GetFolderResponseMessage ResponseClass="Success">
                XmlNode nodeFolderResponseMessage = vmXmlDoc.DocumentElement.SelectSingleNode(
                    EWSRequest.PrefixXPath("m:GetFolderResponse/m:ResponseMessages/m:GetFolderResponseMessage"),
                    xmlNamespaceManager);
                string responseClass = nodeFolderResponseMessage.Attributes["ResponseClass"].Value;

                isEnabled = responseClass.ToUpper() == "SUCCESS" ? true : false;
            }
            catch
            {
                // Assume that Voicemail is not configured if an error occured
                isEnabled = false;
            }

            return isEnabled;
        }

        public static int GetNumberUnreadVoicemails(EWSRequest ewsRequest)
        {
            int unread = 0;

            try
            {
                XmlDocument vmXmlDoc = ewsRequest.GetFolderByDistinguishedFolderId(EWSEnums.DistinguishedFolderId.voicemail);
                XmlNamespaceManager xmlNamespaceManager = EWSRequest.CreateRequestXmlNamespaceManager(vmXmlDoc);

                // Xml looks like --> <t:UnreadCount>0</t:UnreadCount>
                XmlNodeList nodes = vmXmlDoc.SelectNodes(
                    EWSRequest.PrefixXPath("m:GetFolderResponse/m:ResponseMessages/m:GetFolderResponseMessage/m:Folders/t:SearchFolder/t:UnreadCount"),
                    xmlNamespaceManager);

                foreach (XmlNode node in nodes)
                {
                    unread = Convert.ToInt32(node.FirstChild.Value);
                    break; // only 1 node, but break anyway
                }
            }
            catch (Exception e)
            {
                throw (e);
            }

            return unread;
        }

        public static List<VoicemailMessage> GetVoicemails(EWSRequest ewsRequest)
        {
            // All XPath queries start at this level
            string baseQueryPath = "/m:FindItemResponse/m:ResponseMessages/m:FindItemResponseMessage";

            int maxLength = 20;
            int maxVoiceMails = 10;

            try
            {
                List<VoicemailMessage> VMs = new List<VoicemailMessage>();

                XmlDocument vmXmlDoc = ewsRequest.GetFolderItems(
                    new EWSEnums.DistinguishedFolderId[] { EWSEnums.DistinguishedFolderId.voicemail },
                    EWSEnums.BaseShape.Default,
                    EWSEnums.SortOrder.Descending,
                    "item:DateTimeSent",
                    null);

                // Check for success
                //
                // Xml looks like --> <m:FindItemResponseMessage ResponseClass="Success">
                XmlNamespaceManager xmlNamespaceManager = EWSRequest.CreateRequestXmlNamespaceManager(vmXmlDoc);
                XmlNode nodeFindItemResponseMessage = vmXmlDoc.DocumentElement.SelectSingleNode(
                    EWSRequest.PrefixXPath(baseQueryPath),
                    xmlNamespaceManager);
                string responseClass = nodeFindItemResponseMessage.Attributes["ResponseClass"].Value;

                if (responseClass.ToUpper() == "SUCCESS") // Return an empty list if error occured
                { 
                    // Create list of VoicemailMessage objects
                    //
                    XmlNodeList items = vmXmlDoc.SelectNodes(
                        EWSRequest.PrefixXPath(String.Concat(baseQueryPath, "/m:RootFolder/t:Items/t:Message")),
                        xmlNamespaceManager);
                    foreach (XmlNode item in items)
                    {
                        string from = default(string);
                        DateTime received = default(DateTime);
                        string itemId = default(string);
                        bool read = default(bool);

                        received = Convert.ToDateTime(item.SelectSingleNode("t:DateTimeSent", xmlNamespaceManager).InnerText);
                        read = Convert.ToBoolean(item.SelectSingleNode("t:IsRead", xmlNamespaceManager).InnerText);
                        itemId = GetMessageOWAId(ewsRequest, item.SelectSingleNode("t:ItemId/@Id", xmlNamespaceManager).InnerText);
                        from = item.SelectSingleNode("t:From/t:Mailbox/t:Name", xmlNamespaceManager).InnerText;

                        if (from.Length >= maxLength)
                            from = from.Remove(maxLength - 1) + "...";

                        VoicemailMessage vm = new VoicemailMessage(from, received, itemId, read);
                        VMs.Add(vm);

                        if (VMs.Count >= maxVoiceMails)
                            break;
                    }
                }

                return VMs;
            }   
            catch (Exception exception)
            {
                throw exception;
            }
        }

        public static string GetMessageOWAId(EWSRequest ewsRequest, string itemId)
        {
            try
            {
                StringBuilder sbRequest = new StringBuilder();
                sbRequest.AppendLine("<ConvertId xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\" xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\" DestinationFormat=\"OwaId\">");
                sbRequest.AppendLine("<SourceIds>");
                sbRequest.AppendFormat("<t:AlternateId Format=\"EwsLegacyId\" Id=\"{0}\" Mailbox=\"user@example.com\"/>", itemId);
                sbRequest.AppendLine("</SourceIds>");
                sbRequest.AppendLine("</ConvertId>");

                ewsRequest.EWSRequestString = sbRequest.ToString();
                XmlDocument convertIdResponse = ewsRequest.MakeRawSoapRequest(
                    new string[] { "<t:RequestServerVersion Version=\"Exchange2007_SP1\"/>" });

                string baseQueryPath = "/m:ConvertIdResponse/m:ResponseMessages/m:ConvertIdResponseMessage";

                XmlNamespaceManager xmlNamespaceManager = EWSRequest.CreateRequestXmlNamespaceManager(convertIdResponse);
                XmlNode nodeConvertIdResponseMessage = convertIdResponse.DocumentElement.SelectSingleNode(
                        EWSRequest.PrefixXPath(baseQueryPath),
                        xmlNamespaceManager);

                string responseClass = nodeConvertIdResponseMessage.Attributes["ResponseClass"].Value;

                if (responseClass.ToUpper() == "SUCCESS") // Return an empty list if error occured
                {
                    return convertIdResponse.SelectSingleNode(
                        EWSRequest.PrefixXPath(String.Concat(baseQueryPath, "/m:AlternateId/@Id")),
                        xmlNamespaceManager).InnerText;
                }
                else
                    return string.Empty;
            }
            catch (Exception e)
            {
                return default(string);
            }
        }
    }

    public class VoicemailMessage
    {
        public string from {get; set;}
        public DateTime received {get; set;}
        public string itemId { get; set; }
        public bool read { get; set; }

        public VoicemailMessage(string from, DateTime received, string itemId, bool read)
        {
            this.from = from;
            this.received = received;
            this.itemId = itemId;
            this.read = read;
        }
    }
}